package com.tarena.demo.luban.all.main.consumer;

import com.tarena.demo.luban.all.main.service.OrderService;
import com.tarena.demo.luban.protocol.order.param.OrderAddParam;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@Component
@RocketMQMessageListener(
        topic = "order-test-topic",
        consumerGroup = "c-luban-demo-order"
)
public class OrderAddConsumer implements RocketMQListener<OrderAddParam> {

    @Autowired
    OrderService orderService;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Override
    public void onMessage(OrderAddParam message) {

        // 根据消息数据设置一个锁
        String lockKey = "order:add:"+message.getOrderSn()+".lock";
        // 生成随机数value值
        String value = new Random().nextInt(9000)+1000+"";
        // ValueOperations对象做k-v的存储和检索
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        /*
          setIfAbsent() 设置锁的k-v
           key不存在  - 设置key并返回true(获取锁)
           key存在(锁被其他客户端持有) - 不做任何操作并返回false
           设置一个过期时间10秒
         */
        Boolean tryLock = opsForValue.setIfAbsent(lockKey, value, 10, TimeUnit.SECONDS);
        try {
            while(!tryLock){
                Thread.sleep(5000); //没抢到,等5秒再抢
                tryLock = opsForValue.setIfAbsent(lockKey, value, 10, TimeUnit.SECONDS);
            }

            // 捕获业务异常
            orderService.addOrder(message);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            // 释放锁 (value值的比较 一致才能del释放)
            String lockValue = opsForValue.get(lockKey);
            if(value.equals(lockValue)){
                redisTemplate.delete(lockKey);
            }
        }



    }

}

